home *** CD-ROM | disk | FTP | other *** search
/ Revista CD Expert 8 / Revista CD Expert nº 08 CD1.iso / Utilitarios / Programacao / MS-DOS Interrupt List / inter60e / COMBINE.ASM < prev    next >
Encoding:
Assembly Source File  |  1998-03-22  |  11.6 KB  |  495 lines

  1. ; COMBINE.ASM    Interrupt List combiner
  2. ;        by Ralf Brown
  3. ;        last edit: 22mar98
  4.  
  5.         NAME    COMBINE
  6.         TITLE    Combine Interrupt List sections
  7.  
  8. ; declare all the segments in the order in which they are to appear in the
  9. ; executable
  10. CODE    SEGMENT 'CODE'
  11. CODE    ENDS
  12. STACKSEG SEGMENT PUBLIC WORD 'STACK'
  13. STACKSEG ENDS
  14. BUFFERSEG SEGMENT PUBLIC WORD 'DATA'
  15. BUFFERSEG ENDS
  16. ;
  17. DGROUP    GROUP    CODE,STACKSEG,BUFFERSEG
  18.  
  19. ;;------------------------------------------------------------------------
  20.  
  21. FFBLK struc
  22.   ff_reserved    db 15h dup (?)
  23.   ff_attrib    db ?
  24.   ff_ftime    dw ?
  25.   ff_fdate    dw ?
  26.   ff_fsize    dd ?
  27.   ff_fname    db 13 dup (?)
  28. FFBLK ends
  29.  
  30. ;;------------------------------------------------------------------------
  31.  
  32. CODE    SEGMENT 'CODE'
  33.     ORG    100h            ; this is a .COM file
  34.     ASSUME    CS:DGROUP,DS:DGROUP,ES:DGROUP,SS:DGROUP
  35.  
  36. combine:
  37.     jmp    near ptr main
  38.  
  39. banner        db    13,"COMBINE v2.10",9,"Ralf Brown 1996,1998",13,10,"$",26
  40. usage_msg    db    "Usage:",9,"COMBINE [options] dest-dir",13,10
  41.         db    9,"where {dest-dir} is the directory in which to place",13,10
  42.         db    9,"  the combined list ('.' for the current directory)",13,10
  43.         db    10
  44.         db    9,"options:",13,10
  45.         db    9,9,"-d",9,"delete sections after copying",13,10
  46.         db    9,9,"-p",9,"combine PORTS.LST instead of INTERRUP.LST",13,10
  47.         db    10
  48.         db    "All sections of the interrupt/ports list must be in the current directory."
  49.         db    "$"
  50.  
  51. bad_dos_msg    db    "Need DOS 2.0+$"
  52. bad_drive_msg    db    "Invalid destination drive$"
  53. no_mem_msg    db    "Insufficient memory$"
  54. no_files_msg    db    "No section files found!$"
  55. readerr_msg    db    "Read Error$"
  56. writeerr_msg    db    "Write Error$"
  57. diskfull_msg    db    "Disk full? while writing$"
  58. no_disk_msg    db    "Out of space on destination drive",13,10,"$"
  59. retry_msg    db    "Try again with -d to delete while copying$"
  60.  
  61. cant_create_msg db    "Check directory name -- unable to create "
  62. combined_file    db    "INTERRUP.LST",0,"$"
  63. combined_file2    db    "PORTS.LST",0
  64. combined_file2_len equ $-combined_file2
  65. section_file1    db    "INTERRUP.A",0,"$"
  66. section_letter equ section_file1+9
  67. section_file2    db    "   PORTS"
  68. section_file2_len equ $-section_file2
  69. section_file2_ofs equ 3
  70. missing_msg    db    "unavailable (skipped)"
  71. crlf        db    13,10,"$"
  72. section_heading1 db    "Interrupt List, part "
  73. section_hdr_len1 equ $-section_heading1
  74. section_heading2 db    "Ports List, part "
  75. section_hdr_len2 equ $-section_heading2
  76. complete_msg    db    "Done.$"
  77.  
  78. ;
  79. ; flags affecting operation
  80. ;
  81. del_after_copy    db    0
  82. section_file    dw    offset section_file1
  83. section_heading dw    offset section_heading1
  84. section_hdr_len    dw    section_hdr_len1
  85.  
  86. ;
  87. ; data needed while processing
  88. ;
  89. filehandle    equ    di        ; output file's handle
  90. numsections    db    26
  91. dest_drive    db    0
  92. nondefault_dest    db    0
  93. ftime        dw    0
  94. fdate        dw    0
  95. filesize_lo    dw    0
  96. filesize_hi    equ    bp
  97.  
  98. ; (since we don't use disk_buffer until after FindFirst is no longer needed,
  99. ; save memory by overlaying the two)
  100. FindFirst    equ    DGROUP:disk_buffer
  101.  
  102. ;;------------------------------------------------------------------------
  103.  
  104. write_string:
  105.     mov    ah,9
  106.     int    21h
  107.     ret
  108.  
  109. ;;------------------------------------------------------------------------
  110.  
  111. skip_whitespace:
  112.     lodsb
  113.     cmp    al,' '
  114.     je    skip_whitespace
  115.     cmp    al,9
  116.     je    skip_whitespace
  117.     dec    si            ; unget the last character
  118.     ; set ZF to indicate whether we got to end of cmdline
  119.     cmp    al,0Dh
  120.     ret
  121.  
  122. ;;------------------------------------------------------------------------
  123.  
  124. get_destination_file:
  125.     mov    bx,si            ; remember start of destination name
  126. get_dest_file_loop:
  127.     lodsb
  128.     cmp    al,' '
  129.     je    got_dest_end
  130.     cmp    al,9
  131.     je    got_dest_end
  132.     cmp    al,0Dh
  133.     jne    get_dest_file_loop
  134. got_dest_end:
  135.     dec    si            ; unget last character
  136.     mov    di,si
  137.     mov    al,[si-1]        ; check end of path -- is it terminated
  138.     cmp    al,'\'            ;   by a slash or backslash?
  139.     je    dest_has_slash
  140.     cmp    al,'/'
  141.     je    dest_has_slash
  142.     cmp    al,':'
  143.     je    dest_has_slash
  144.     mov    al,'\'
  145.     stosb
  146. dest_has_slash:
  147.     mov    si,offset combined_file
  148. dest_copy_loop:
  149.     lodsb
  150.     stosb
  151.     cmp    al,0
  152.     jne    dest_copy_loop
  153.     ; OK, now open the destination file
  154.     ; (BX is still pointing at start of pathname)
  155.     cmp    byte ptr [bx+1],':'
  156.     jne    got_dest_drive
  157.     mov    al,[bx]
  158.     and    al,0DFh            ; force to uppercase
  159.     sub    al,'A'
  160.     jb    got_dest_drive
  161.     cmp    al,dest_drive
  162.     je    got_dest_drive
  163.     mov    dest_drive,al
  164.     mov    nondefault_dest,al
  165. got_dest_drive:
  166.     mov    ah,3Ch            ; create the output file
  167.     xor    cx,cx            ; no special file attributes
  168.     mov    dx,bx
  169.     int    21h
  170.     mov    dx,offset cant_create_msg
  171.     jc    exit_with_err_2
  172.     mov    filehandle,ax
  173.     ret
  174.  
  175. ;;------------------------------------------------------------------------
  176.  
  177. check_total_size:
  178.     mov    byte ptr section_letter,'A'-1
  179.     mov    ah,1Ah            ; set DTA
  180.     mov    dx,offset FindFirst
  181.     int    21h
  182.     xor    si,si            ; keep track of # of sections found
  183. check_size_loop:
  184.     inc    byte ptr section_letter
  185.     cmp    byte ptr section_letter,'Z'
  186.     ja    short get_free_space
  187.     mov    ah,4Eh            ; find first
  188.     mov    cx,001Fh        ; ...regardless of attribute
  189.     mov    dx,section_file
  190.     int    21h
  191.     jc    check_size_loop
  192.     inc    si            ; another section found
  193.     mov    ax,FindFirst.ff_ftime
  194.     mov    ftime,ax
  195.     mov    ax,FindFirst.ff_fdate
  196.     mov    fdate,ax
  197.     mov    ax,word ptr FindFirst.ff_fsize
  198.     mov    dx,word ptr FindFirst.ff_fsize+2
  199.     cmp    del_after_copy,0
  200.     je    count_full_size
  201.     cmp    nondefault_dest,0
  202.     jnz    count_full_size
  203.     cmp    dx,filesize_hi
  204.     jb    check_size_loop
  205.     ja    check_size_bigger
  206.     cmp    ax,filesize_lo
  207.     jbe    check_size_loop
  208. check_size_bigger:
  209.     mov    filesize_lo,ax
  210.     mov    filesize_hi,dx
  211.     jmp    check_size_loop
  212.  
  213. count_full_size:
  214.     add    filesize_lo,ax
  215.     adc    filesize_hi,dx
  216.     jmp    check_size_loop
  217.  
  218. get_free_space:
  219.     test    si,si            ; check number of sections found
  220.     mov    dx,offset no_files_msg
  221.     jz    short exit_with_err_2
  222.     mov    dl,dest_drive
  223.     inc    dx
  224.     mov    ah,36h            ; get free disk space
  225.     int    21h
  226.     cmp    ax,0FFFFh
  227.     jne    got_free_space
  228.     mov    dx,offset bad_drive_msg
  229. exit_with_err_2:
  230.     jmp    near ptr exit_with_errmsg
  231. got_free_space:
  232.     mul    cx            ; DX:AX <- AX*CX
  233.     mov    cx,dx            ; store high half of intermediate
  234.     mul    bx            ; DX:AX <- low(AX*CX)*BX
  235.     xchg    ax,bx            ; store low half of second interm.
  236.     xchg    cx,dx            ; store high half of second interm.
  237.     mul    dx            ; DX:AX <- high(AX*CX)*BX
  238.     xchg    ax,bx            ; DX:BX:0000h + CX:AX = result
  239.     add    bx,cx
  240.     adc    dx,0            ; DX:BX:AX = AX*BX*CX = free space
  241.     jnz    plenty_free_space    ; >4G free?
  242.     sub    ax,filesize_lo
  243.     sbb    bx,filesize_hi
  244.     jnb    plenty_free_space
  245. not_enough_space:
  246.     mov    dx,offset no_disk_msg
  247.     call    write_string
  248.     cmp    nondefault_dest,0
  249.     jnz    size_check_failed
  250.     cmp    del_after_copy,0
  251.     jne    size_check_failed
  252.     mov    dx,offset retry_msg
  253.     call    write_string
  254. size_check_failed:
  255.     mov    al,2
  256.     jmp    exit
  257. plenty_free_space:
  258.     ret
  259.  
  260. ;;------------------------------------------------------------------------
  261.  
  262. check_section_header:
  263.     push    si
  264.     push    di
  265.     mov    si,offset DGROUP:disk_buffer
  266.     mov    di,section_heading
  267.     mov    cx,section_hdr_len
  268.     or    cx,cx
  269.     rep    cmpsb
  270.     jnz    not_section_heading
  271. scan_curr_section:
  272.     lodsb
  273.     cmp    al,' '            ; scan for the " of "
  274.     jne    scan_curr_section
  275.     add    si,3            ; skip "of "
  276.     xor    cl,cl
  277. num_sections_loop:
  278.     lodsb
  279.     sub    al,'0'
  280.     jb    num_sections_done
  281.     cmp    al,9
  282.     ja    num_sections_done
  283.     mov    ch,al
  284.     mov    al,10
  285.     mul    cl
  286.     mov    cl,al
  287.     add    cl,ch
  288.     jmp    num_sections_loop
  289. num_sections_done:
  290.     mov    numsections,cl
  291. got_num_sections:
  292. not_section_heading:    
  293.     pop    di
  294.     pop    si
  295.     ret
  296.  
  297. ;;------------------------------------------------------------------------
  298.  
  299. ; in:    SI = file handle for current section
  300. copy_section:
  301.     mov    ax,4201h
  302.     xor    cx,cx
  303.     xor    dx,dx
  304.     mov    bx,filehandle
  305.     int    21h
  306.     mov    filesize_lo,ax
  307.     mov    filesize_hi,dx
  308. copy_section_loop:
  309.     mov    ah,3Fh
  310.     mov    bx,si
  311.     mov    cx,disk_buffer_end - disk_buffer
  312.     mov    dx,offset DGROUP:disk_buffer
  313.     int    21h
  314.     jc    copy_read_error
  315.     mov    cx,ax            ; write same number of bytes read
  316.     mov    ah,40h
  317. ;;    mov    dx,offset DGROUP:disk_buffer
  318.     mov    bx,filehandle
  319.     int    21h
  320.     mov    dx,offset writeerr_msg
  321.     jc    copy_error
  322.     mov    dx,offset diskfull_msg
  323.     cmp    ax,cx
  324.     jb    copy_error
  325.     ; check for section header at start of buffer, and extract number
  326.     ; of sections from it
  327.     push    cx
  328.     call    check_section_header
  329.     pop    ax
  330.     cmp    ax,disk_buffer_end - disk_buffer ; continue until only partial
  331.     je    copy_section_loop         ;   buffer read (EOF hit)
  332.     ret
  333.  
  334. copy_read_error:
  335.     mov    dx,offset readerr_msg
  336. copy_error:
  337.     ; truncate output to size before section was started
  338.     push    dx            ; store error message
  339.     mov    ax,4200h
  340.     mov    cx,filesize_hi
  341.     mov    dx,filesize_lo
  342.     mov    bx,filehandle
  343.     int    21h
  344.     mov    ah,40h
  345.     xor    cx,cx            ; write zero bytes to truncate
  346.     int    21h
  347.     pop    dx            ; get back error message
  348.     ;; fall through to exit_with_errmsg ;;
  349.  
  350. ;;------------------------------------------------------------------------
  351.  
  352. exit_with_errmsg:
  353.     call    write_string
  354.     ; exit with errorlevel 1
  355.     mov    al,01h
  356.     jmp    near ptr exit
  357.  
  358. main:
  359.     ASSUME    CS:DGROUP, DS:DGROUP, ES:DGROUP, SS:DGROUP
  360.     mov    dx,offset banner
  361.     call    write_string
  362.     ; relocate the stack
  363.     mov    sp,offset DGROUP:stackbot
  364.     ; ensure that we have enough memory
  365.     mov    ax,cs
  366.     add    ax,1000h        ; require 64K memory
  367.     cmp    ax,ds:[0002h]        ; is end of mem at least 64K above CS?
  368.     mov    dx,offset no_mem_msg
  369.     ja    exit_with_errmsg
  370.     mov    si,81h            ; point at start of cmdline
  371.     mov    bl,[si-1]        ; get length of cmdline
  372.     mov    bh,0
  373.     mov    byte ptr [bx+si],0Dh    ; ensure cmdline properly terminated
  374.     cld
  375.     call    skip_whitespace
  376.     mov    dx,offset usage_msg
  377.     jz    exit_with_errmsg
  378. get_cmdline_switches:
  379.     call    skip_whitespace
  380.     jz    not_a_switch
  381.     cmp    al,'-'            ; is it a switch?
  382.     jne    not_a_switch
  383.     lodsb                ; get the switch character
  384.     lodsb                ; get the switch itself
  385.     and    al,0DFh            ; force to uppercase
  386.     cmp    al,'P'
  387.     je    want_ports
  388.     cmp    al,'D'
  389. ;;    mov    dx,offset usage_msg
  390.     jne    exit_with_errmsg
  391.     mov    del_after_copy,1
  392.     jmp    get_cmdline_switches
  393. want_ports:
  394.     jmp    config_for_ports
  395. not_a_switch:
  396.     mov    ah,19h            ; get default drive
  397.     int    21h
  398.     mov    dest_drive,al
  399.     mov    ah,30h
  400.     int    21h
  401.     cmp    al,2
  402.     mov    dx,offset bad_dos_msg
  403.     jb    exit_with_errmsg
  404.     call    get_destination_file
  405.     xor    filesize_hi,filesize_hi
  406.     call    check_total_size
  407.     ;
  408.     ; OK, all the preliminaries are done now, so go concatenate the
  409.     ; sections of the interrupt list
  410.     ;
  411.     mov    al,'A'-1
  412. concat_loop:
  413.     inc    ax
  414.     mov    section_letter,al
  415.     sub    al,'A'-1
  416.     cmp    al,numsections
  417.     ja    concat_done
  418.     mov    dx,section_file
  419.     call    write_string
  420.     mov    ax,3D00h
  421.     int    21h
  422.     mov    dx,offset missing_msg
  423.     jc    concat_loop_end
  424.     mov    si,ax
  425.     call    copy_section
  426.     mov    bx,si            ; BX <- section file's handle
  427.     mov    ah,3Eh            ; DOS function: close file handle
  428.     int    21h
  429.     cmp    del_after_copy,0
  430.     je    concat_no_del
  431.     mov    ah,41h            ; DOS function: delete file
  432.     mov    dx,section_file
  433.     int    21h
  434. concat_no_del:
  435.     mov    dx,offset crlf
  436. concat_loop_end:
  437.     call    write_string
  438.     mov    al,section_letter
  439.     jmp    concat_loop
  440.  
  441. concat_done:
  442.     mov    dx,offset complete_msg
  443.     call    write_string
  444.     mov    al,00h            ; successful completion
  445. exit:
  446.     push    ax
  447.     mov    dx,offset crlf
  448.     call    write_string
  449.     mov    ax,5701h        ; (set file time & date)
  450.     mov    bx,filehandle
  451.     mov    cx,ftime        ; set timestamp of combined file to
  452.     mov    dx,fdate        ;   be that of the last of the sections
  453.     int    21h
  454.     mov    ah,3Eh            ; DOS function: close file handle
  455.     int    21h
  456.     pop    ax
  457.     mov    ah,4Ch
  458.     int    21h
  459.  
  460. config_for_ports:
  461.     mov    section_heading,offset section_heading2
  462.     mov    section_hdr_len,section_hdr_len2
  463.     push    di
  464.     push    si
  465.     push    cx
  466.     ;; copy combined_file2 over combined_file
  467.     mov    cx,combined_file2_len
  468.     mov    si,offset combined_file2
  469.     mov    di,offset combined_file
  470.     rep    movsb
  471.     ;; copy section_file2 over section_file1
  472.     mov    cx,section_file2_len
  473.     mov    si,offset section_file2
  474.     mov    di,offset section_file1
  475.     rep    movsb
  476.     pop    cx
  477.     pop    si
  478.     pop    di
  479.     add    section_file,section_file2_ofs
  480.     jmp    get_cmdline_switches
  481.  
  482. CODE ENDS
  483.  
  484. STACKSEG SEGMENT PUBLIC WORD 'STACK'
  485. stacktop dw    160 dup (?)
  486. stackbot label byte
  487. STACKSEG ENDS
  488.  
  489. BUFFERSEG SEGMENT PUBLIC WORD 'DATA'
  490. disk_buffer db 62*1024 dup (?)
  491. disk_buffer_end label byte
  492. BUFFERSEG ENDS
  493.  
  494.     END combine
  495.